﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition.Hosting;
using Microsoft.VisualStudio.Shell.Interop;
using System.ComponentModel.Composition.Primitives;

namespace VsxFactory.Modeling.StrategyManager.Strategies
{
    class SafeCompositionContainer : CompositionContainer
    {
        public SafeCompositionContainer(List<ComposablePartCatalog> catalogs, VisualStudioStrategyContext context, IVsActivityLog log)
            : base(CreateSafeProvidersList(catalogs, context, log).ToArray()) {
            foreach (var provider in Providers.OfType<SafeCatalogExportProvider>()) {
                provider.SourceProvider = this;
            }
        }

        private static IEnumerable<ExportProvider> CreateSafeProvidersList(List<ComposablePartCatalog> catalogs, VisualStudioStrategyContext context, IVsActivityLog log) {
            foreach (var catalog in catalogs) {
                var provider = new CatalogExportProvider(catalog);
                yield return new SafeCatalogExportProvider(catalog, context, log);
            }
        }

        class SafeCatalogExportProvider : CatalogExportProvider
        {
            private VisualStudioStrategyContext context;
            private IVsActivityLog log;
            bool inError;
            public SafeCatalogExportProvider(ComposablePartCatalog catalog, VisualStudioStrategyContext context, IVsActivityLog log)
                : base(catalog) {
                this.context = context;
                this.log = log;
            }

            protected override IEnumerable<Export> GetExportsCore(ImportDefinition definition, AtomicComposition atomicComposition) {
                if (!inError) {
                    try {
                        return base.GetExportsCore(definition, atomicComposition);
                    }
                    catch (System.Reflection.ReflectionTypeLoadException rex) {
                        context.WriteError("Error when loading strategies ({0})", rex.LoaderExceptions[0].Message);
                        if (log != null)
                            log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_INFORMATION, this.ToString(), string.Format(System.Globalization.CultureInfo.CurrentCulture, "MEF composition error - Reflection error {0}", rex.LoaderExceptions[0].Message));
                    }
                    catch (Exception ex) {
                        if (log != null)
                            log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_INFORMATION, this.ToString(), string.Format(System.Globalization.CultureInfo.CurrentCulture, "MEF composition error {0}", ex));
                    }
                    inError = true;
                }

                return Enumerable.Empty<Export>();
            }
        }
    }
}
